package com.greenzebras.geocache;

import java.io.IOException;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.greenzebras.geocache.constant.GeocacheConstants;

public class GeocacheLocationSearchActivity extends Activity {

	EditText searchText;
	Button searchButton;
	ListView listviewResult;
	Geocoder myGeocoder;
	List<Address> addresses = null;
	AddressSearchAdapter addressSearchAdapter = null;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.location_search);
		initializeFields();
		initializeSearchButton();
		initializeUseCurrentLocationButton();

		myGeocoder = new Geocoder(this);
		if (!Geocoder.isPresent()) {
			Toast.makeText(GeocacheLocationSearchActivity.this,
					getString(R.string.geocoder_not_present_error),
					Toast.LENGTH_LONG).show();
		}
		initializeListViewResult();
	}

	OnItemClickListener listviewResultOnItemClickListener = new OnItemClickListener() {

		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,
				long id) {
			Address addr = (Address) parent.getItemAtPosition(position);
			String address = buildAddressToDisplay(addr);
			double lat = addr.getLatitude();
			double lon = addr.getLongitude();

			// create the details intent
			Intent cacheCreateIntent = new Intent(
					GeocacheLocationSearchActivity.this,
					GeocacheCreateActivity.class);

			// add the address to the details intent
			cacheCreateIntent.putExtra("addressForCacheCreate", address);
			cacheCreateIntent.putExtra("latitudeForCacheCreate",
					Double.toString(lat));
			cacheCreateIntent.putExtra("longitudeForCacheCreate",
					Double.toString(lon));

			// start the details activity
			startActivityForResult(cacheCreateIntent,
					GeocacheConstants.CACHE_CREATE);
		}

	};

	private void initializeListViewResult() {
		listviewResult = (ListView) findViewById(R.id.list);
		listviewResult
				.setOnItemClickListener(listviewResultOnItemClickListener);
	}

	private void searchFromLocationName(String name) {
		try {
			addresses = myGeocoder.getFromLocationName(name,
					GeocacheConstants.MAX_RESULT);

			if ((addresses == null) || (addresses.isEmpty())) {
				Toast.makeText(GeocacheLocationSearchActivity.this,
						getString(R.string.location_search_error_string), 5)
						.show();
			} else {
				hideUseCurrentLocationButton();

				addressSearchAdapter = new AddressSearchAdapter(
						this, android.R.layout.simple_list_item_1, addresses);
				listviewResult.setAdapter(addressSearchAdapter);

				Toast.makeText(GeocacheLocationSearchActivity.this,
						getString(R.string.location_loaded_confirmation),
						Toast.LENGTH_LONG).show();
			}

		} catch (IOException e) {
			e.printStackTrace();
			Toast.makeText(GeocacheLocationSearchActivity.this,
					getString(R.string.location_search_io_error),
					Toast.LENGTH_LONG).show();
		}
	}

	public class AddressSearchAdapter extends ArrayAdapter<Address> {
		Context _context;

		public AddressSearchAdapter(Context context, int textViewResourceId,
				List<Address> objects) {
			super(context, textViewResourceId, objects);
			_context = context;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			int maxAddressLineIndex = getItem(position)
					.getMaxAddressLineIndex();
			String addressLine = "";

			for (int j = 0; j <= maxAddressLineIndex; j++) {
				addressLine += getItem(position).getAddressLine(j) + ",";
			}

			TextView rowAddress = new TextView(_context);
			rowAddress.setText(addressLine);
			rowAddress.setTextColor(Color.BLACK);

			return rowAddress;
		}

	}

	private void initializeFields() {
		searchText = (EditText) findViewById(R.id.searchtext);
		searchText.setText(GeocacheConstants.DEFAULT_SEARCH_TEXT);
	}

	private void initializeSearchButton() {
		Button.OnClickListener searchButtonOnClickListener = new Button.OnClickListener() {
			@Override
			public void onClick(View arg0) {
				String searchString = searchText.getText().toString();
				if (searchString == null || searchString.isEmpty()) {
					String errorString = getString(R.string.location_search_string_required);
					ForegroundColorSpan fSpan = new ForegroundColorSpan(
							GeocacheConstants.FOREGROUND_COLOR);
					SpannableStringBuilder ssBuilder = new SpannableStringBuilder(
							errorString);
					ssBuilder.setSpan(fSpan, 0, errorString.length(), 0);
					searchText.setError(ssBuilder);
				} else {
					searchFromLocationName(searchString);
				}
			}
		};

		searchButton = (Button) findViewById(R.id.search_button);
		searchButton.setText(R.string.search_button);
		searchButton.setOnClickListener(searchButtonOnClickListener);
	}

	// TODO: Add null check
	private String buildAddressToDisplay(Address addr) {
		String address = addr.getAddressLine(1) + "\n" + addr.getAddressLine(2)
				+ "\n" + addr.getAddressLine(3) + "\n" + addr.getAddressLine(4);
		return address;
	}

	private void initializeUseCurrentLocationButton() {
		((Button) findViewById(R.id.use_current_location_button))
				.setOnClickListener(new OnClickListener() {

					@Override
					public void onClick(View v) {
						// retrieve location
						LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
						Criteria crit = new Criteria();

						String towers = locationManager.getBestProvider(crit,
								false);
						Location location = locationManager
								.getLastKnownLocation(towers);
						if (location != null) {
							// create the details intent
							Intent cacheCreateIntent = new Intent(
									GeocacheLocationSearchActivity.this,
									GeocacheCreateActivity.class);

							cacheCreateIntent.putExtra(
									"latitudeForCacheCreate",
									Double.toString(location.getLatitude()));
							cacheCreateIntent.putExtra(
									"longitudeForCacheCreate",
									Double.toString(location.getLongitude()));

							// start the details activity
							startActivityForResult(cacheCreateIntent,
									GeocacheConstants.CACHE_CREATE);
						} else {
							Toast.makeText(
									getApplicationContext(),
									R.string.location_provider_unavailable_message,
									Toast.LENGTH_LONG).show();
							hideUseCurrentLocationButton();
						}
					}
				});

	}

	private void hideUseCurrentLocationButton() {
		((Button) findViewById(R.id.use_current_location_button))
				.setVisibility(View.GONE);
	}

	private void showUseCurrentLocationButton() {
		((Button) findViewById(R.id.use_current_location_button))
				.setVisibility(View.VISIBLE);
	}

	@Override
	protected void onResume() {
		super.onResume();
		showUseCurrentLocationButton();
		if (null != addresses) {
			addresses.clear();
			addressSearchAdapter.notifyDataSetChanged();
		}
	}
}